import time, json

def checksum(data):
    return sum(data) & 0xFF

def bcd_plus_33_to_decimal(bcd_string):
    # 将16进制字符串转换为字节数组
    bytes_array = bytes.fromhex(bcd_string)
    decimal_result = 0

    # 处理每个字节
    for byte in bytes_array:
        # 还原原始BCD编码
        original_bcd = byte - 0x33
        # 将BCD转换为十进制
        high = (original_bcd >> 4) & 0xF  # 获取高四位
        low = original_bcd & 0xF          # 获取低四位
        if high > 9 or low > 9:           # 检查BCD码是否有效
            raise ValueError("Invalid BCD Code")
        # 累加计算最终的十进制结果
        decimal_result = decimal_result * 100 + high * 10 + low

    return decimal_result

def send(ser, order, addr):
    data = [0x68] + addr + [0x68]
    if order == "clr":
        data += [0x04, 0x04, 0x33, 0xF3, 0xF3, 0x3B]
    elif order == "send":
        data += [0x04, 0x08, 0x37, 0x33, 0x34, 0x34, 0x00, 0x02, 0xAA, 0xE9]
    elif order == "read":
        data += [0x04, 0x06, 0x34, 0xF3, 0xF3, 0x3B, 0x34, 0x34]
    elif order == "read_p":
        data += [0x11, 0x04, 0x33, 0x33, 0x36, 0x35]
    elif order == "read_i":
        data += [0x11, 0x04, 0x33, 0x34, 0x35, 0x35]
    elif order == "read_u":
        data += [0x11, 0x04, 0x33, 0x34, 0x34, 0x35]
    data += [checksum(data), 0x16]
    ser.write(bytes(data))

    received_data = ser.read_until(b'\x16').hex()

    if not received_data:
        return False
    
    if order == "read":
        L = int(received_data[18:20])
        if L == 5:
            # print(f"{order} error")
            return False
        elif L == 11:
            timestamp = received_data[30:42]
            return True
            return int(timestamp) - 333333333333333333333333
        else:
            raise
    elif order in ["clr", "send"]:
        if received_data[-8:-6] == "84":
            return True
        else:
            raise
            print(f"{order} error")
            return False
    elif order == "read_p":
        # print(received_data)
        if received_data[16:18] == "d1":
            raise
        # print(received_data[-10:-4])
        # p_data = received_data[-10:-4]
        p_data = received_data[-6:-4] + received_data[-8:-6] + received_data[-10:-8]
        # p = (int(p_data[-2:], 16) - 0x33)* 100 + int(p_data[-4:-2], 16) - 0x33 + (int(p_data[-6:-4], 16) - 0x33) * 0.01
        p = bcd_plus_33_to_decimal(p_data) / 1e2
        # print(p)
        return p
    elif order == "read_i":
        if received_data[16:18] == "d1":
            raise
        i_data = received_data[-6:-4] + received_data[-8:-6] + received_data[-10:-8]
        i = bcd_plus_33_to_decimal(i_data) / 1e2
        return i
    elif order == "read_u":
        # print(received_data)
        if received_data[16:18] == "d1":
            raise
        u_data = received_data[-6:-4] + received_data[-8:-6]
        u = bcd_plus_33_to_decimal(u_data) / 1e1
        return u
        
def clr_all(ser, addr_dict):
    for addr in addr_dict.values():
        send(ser, "clr", addr)
    return

def explore(ser, node, addr_dict):
    res = []

    clr_all(ser, addr_dict)

    send(ser, "send", addr_dict[node])
    time.sleep(20)

    for receiver in addr_dict.keys():
        if send(ser, "read", addr_dict[receiver]):
            res.append(receiver)

    print(node, res)
    return res

class CustomEncoder(json.JSONEncoder):
    def encode(self, obj):
        if isinstance(obj, dict):
            items = []
            for key, value in obj.items():
                # 对于第一级键值对，单独处理
                if isinstance(value, dict):
                    items.append(f'"{key}":' + json.dumps(value, ensure_ascii=False, separators=(',', ':')))
                else:
                    items.append(f'"{key}":{json.dumps(value, ensure_ascii=False)}')
            return '{\n  ' + ',\n  '.join(items) + '\n}'
        return super().encode(obj)